package clipboard

import (
	"fmt"
	"os/exec"
	"runtime"
	"strings"
	"time"

	"golang.design/x/clipboard"
)

// ClipboardManager 剪贴板管理器
type ClipboardManager struct {
	parser *ExcelClipboardParser
}

// NewClipboardManager 创建剪贴板管理器
func NewClipboardManager() (*ClipboardManager, error) {
	// 初始化剪贴板
	err := clipboard.Init()
	if err != nil {
		return nil, fmt.Errorf("初始化剪贴板失败: %v", err)
	}

	return &ClipboardManager{
		parser: NewExcelClipboardParser(),
	}, nil
}

// GetExcelData 获取Excel数据
func (cm *ClipboardManager) GetExcelData() (*ParseResult, error) {
	// 尝试获取HTML内容
	htmlContent, err := cm.getHTMLContent()
	if err != nil {
		return nil, fmt.Errorf("获取HTML内容失败: %v", err)
	}

	// 解析Excel数据
	result := cm.parser.ParseExcelHTML(htmlContent)
	return result, nil
}

// getHTMLContent 获取HTML格式的剪贴板内容
func (cm *ClipboardManager) getHTMLContent() (string, error) {
	// 首先尝试通过golang.design/x/clipboard获取
	// 注意：这个库目前不支持HTML格式，所以我们需要使用平台特定的方法

	switch runtime.GOOS {
	case "windows":
		return cm.getHTMLWindows()
	case "darwin":
		return cm.getHTMLMacOS()
	case "linux":
		return cm.getHTMLLinux()
	default:
		return "", fmt.Errorf("不支持的平台: %s", runtime.GOOS)
	}
}

// getHTMLWindows Windows平台获取HTML剪贴板
func (cm *ClipboardManager) getHTMLWindows() (string, error) {
	// 这里使用简化的方法，实际实现需要Windows API调用
	// 由于需要复杂的Windows API调用，这里提供一个基础实现
	// 实际项目中可以使用github.com/go-ole/go-ole等库来完整实现

	// 尝试读取剪贴板内容，看看是否包含HTML标记
	text := clipboard.Read(clipboard.FmtText)
	textStr := string(text)

	lowerText := strings.ToLower(textStr)
	if strings.Contains(lowerText, "<html") ||
		strings.Contains(lowerText, "<table") ||
		strings.Contains(lowerText, "mso-") ||
		strings.Contains(lowerText, "urn:schemas-microsoft-com:office:excel") {
		return textStr, nil
	}

	return "", fmt.Errorf("剪贴板中没有HTML内容")
}

// getHTMLMacOS macOS平台获取HTML剪贴板
func (cm *ClipboardManager) getHTMLMacOS() (string, error) {
	// 使用pbpaste命令获取HTML内容，添加超时机制
	cmd := exec.Command("pbpaste", "-Prefer", "public.html")

	output, err := cm.execCommandWithTimeout(cmd, 3*time.Second)
	if err != nil {
		return "", fmt.Errorf("执行pbpaste失败: %v", err)
	}

	content := string(output)
	if len(content) == 0 {
		return "", fmt.Errorf("剪贴板为空")
	}

	lowerContent := strings.ToLower(content)
	if strings.Contains(lowerContent, "<html") ||
		strings.Contains(lowerContent, "<table") ||
		strings.Contains(lowerContent, "mso-") ||
		strings.Contains(lowerContent, "urn:schemas-microsoft-com:office:excel") {
		return content, nil
	}

	return "", fmt.Errorf("剪贴板中没有HTML内容")
}

// execCommandWithTimeout 执行命令并带超时机制
func (cm *ClipboardManager) execCommandWithTimeout(cmd *exec.Cmd, timeout time.Duration) ([]byte, error) {
	done := make(chan struct{})
	var output []byte
	var err error

	go func() {
		output, err = cmd.CombinedOutput()
		close(done)
	}()

	select {
	case <-done:
		return output, err
	case <-time.After(timeout):
		// 尝试杀死进程
		if cmd.Process != nil {
			cmd.Process.Kill()
		}
		return nil, fmt.Errorf("命令执行超时")
	}
}

// getHTMLLinux Linux平台获取HTML剪贴板
func (cm *ClipboardManager) getHTMLLinux() (string, error) {
	// 检查是否有xclip
	if _, err := exec.LookPath("xclip"); err == nil {
		// 尝试获取HTML内容
		cmd := exec.Command("xclip", "-selection", "clipboard", "-t", "text/html", "-o")
		output, err := cm.execCommandWithTimeout(cmd, 3*time.Second)
		if err == nil && len(output) > 0 {
			content := string(output)
			lowerContent := strings.ToLower(content)
			if strings.Contains(lowerContent, "<html") ||
				strings.Contains(lowerContent, "<table") ||
				strings.Contains(lowerContent, "mso-") ||
				strings.Contains(lowerContent, "urn:schemas-microsoft-com:office:excel") {
				return content, nil
			}
		}
	}

	// 检查是否有xsel
	if _, err := exec.LookPath("xsel"); err == nil {
		// xsel不支持直接获取HTML格式，尝试获取文本
		cmd := exec.Command("xsel", "--clipboard", "--output")
		output, err := cm.execCommandWithTimeout(cmd, 3*time.Second)
		if err == nil {
			content := string(output)
			lowerContent := strings.ToLower(content)
			if strings.Contains(lowerContent, "<html") ||
				strings.Contains(lowerContent, "<table") ||
				strings.Contains(lowerContent, "mso-") ||
				strings.Contains(lowerContent, "urn:schemas-microsoft-com:office:excel") {
				return content, nil
			}
		}
	}

	return "", fmt.Errorf("剪贴板中没有HTML内容")
}

// WriteText 写入文本到剪贴板
func (cm *ClipboardManager) WriteText(text string) error {
	clipboard.Write(clipboard.FmtText, []byte(text))
	return nil
}

// ReadText 从剪贴板读取文本
func (cm *ClipboardManager) ReadText() (string, error) {
	data := clipboard.Read(clipboard.FmtText)
	return string(data), nil
}
